package com.yn.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.yn.common.enums.AppointmentStatusEnum;
import com.yn.common.enums.BusinessTypeEnum;
import com.yn.common.exception.TransitException;
import com.yn.common.model.system.SystemCity;
import com.yn.common.model.system.SystemConfig;
import com.yn.common.model.zy.SubscribeInfoDO;
import com.yn.common.model.zy.TDoctorInfoDO;
import com.yn.common.model.zy.TOrganInfoDO;
import com.yn.common.page.BasePage;
import com.yn.common.request.sc.PageParamRequest;
import com.yn.common.request.zy.*;
import com.yn.common.response.zy.DiagnosisInfoResponse;
import com.yn.common.response.zy.InstPageInfoResponse;
import com.yn.common.response.zy.InstitutionInfoResponse;
import com.yn.common.response.zy.DictResponse;
import com.yn.common.utils.PhoneValidator;
import com.yn.common.utils.genutils.CommonResult;
import com.yn.service.dao.zy.SubscribeInfoMapper;
import com.yn.service.service.ISubscribeInfoService;
import com.yn.service.service.SystemCityService;
import com.yn.service.service.SystemConfigService;
import com.yn.service.service.UserService;
import com.yn.service.zy.TDoctorInfoService;
import com.yn.service.zy.TOrganInfoService;
import com.yn.service.zy.model.dto.TDoctorInfoOutDTO;
import com.yn.service.zy.model.dto.TOrganInfoDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 预约信息表 服务实现类
 * </p>
 *
 * @author xuquanjun
 * @since 2025-07-07
 */
@Service
public class SubscribeInfoServiceImpl extends ServiceImpl<SubscribeInfoMapper, SubscribeInfoDO> implements ISubscribeInfoService {

    @Resource
    private UserService userService;

    @Resource
    private TDoctorInfoService tDoctorInfoService;

    @Resource
    private TOrganInfoService tOrganInfoService;

    @Resource
    private SystemCityService systemCityService;

    @Resource
    private SystemConfigService systemConfigService;

    @Override
    @Transactional
    public String apptAddSave(ApptAddInfoRequest request) {

        boolean valid = PhoneValidator.isValid(request.getUserOrderPhone());
        if (!valid) {
            throw  new TransitException("手机号格式错误");
        }
        //获取用户id
        Integer userId = userService.getUserIdException();
        SubscribeInfoDO transform = ApptAddInfoRequest.transform(request);
        transform.setAppUserId(userId);
        transform.setUpdateUserId(userId);
        //根据用户id，专家id，业务类型,状态不为已取消，预约时间大于当前时间查询预约表信息
        SubscribeInfoDO one = lambdaQuery().eq(SubscribeInfoDO::getAppUserId, userId)
                .eq(SubscribeInfoDO::getBusinessId, request.getDoctorId())
                .eq(SubscribeInfoDO::getBusinessType, request.getBusinessType())
                .gt(SubscribeInfoDO::getApptTime, new Date())
                .one();
        if(one != null && Objects.equals(one.getStatus(), AppointmentStatusEnum.SUBMITTED.getCode())){
            throw new TransitException("您已预约过此专家，请勿重复预约");
        }
        if (one != null && Objects.equals(one.getStatus(), AppointmentStatusEnum.SUCCESS.getCode())){
            throw new TransitException("您已预约成功，请勿重复预约");
        }
        boolean save = this.save(transform);
        if(!save){
            throw new TransitException("保存失败");
        }
        return transform.getId().toString();
    }

    @Override
    @Transactional
    public String orgBedAddSave(InstAppointmentRequest request) {
        boolean valid = PhoneValidator.isValid(request.getUserOrderPhone());
        if (!valid) {
            throw  new TransitException("手机号格式错误");
        }
        //获取用户id
        Integer userId = userService.getUserIdException();
        SubscribeInfoDO transform = InstAppointmentRequest.transform(request);
        transform.setAppUserId(userId);
        transform.setUpdateUserId(userId);
        //根据用户id，机构id，业务类型查询预约表信息
        SubscribeInfoDO one = lambdaQuery().eq(SubscribeInfoDO::getAppUserId, userId)
                .eq(SubscribeInfoDO::getBusinessId, request.getOrganId())
                .eq(SubscribeInfoDO::getBusinessType, request.getBusinessType())
                .ne(SubscribeInfoDO::getStatus, AppointmentStatusEnum.CANCELED.getCode())
                .one();
        if(one != null){
            throw new TransitException("您已预约过该专家");
        }
        boolean save = this.save(transform);
        if(!save){
            throw new TransitException("保存失败");
        }
        return transform.getId().toString();
    }

    @Override
    public DiagnosisInfoResponse showInpatientDetail(Integer id) {
        //根据id查询预约表信息
        SubscribeInfoDO subscribeInfoDO = this.getById(id);
        if(subscribeInfoDO == null){
            throw new TransitException("预约信息不存在");
        }
        DiagnosisInfoResponse transform = DiagnosisInfoResponse.transform(subscribeInfoDO);
        //根据业务id查询专家表得到专家名称
        TDoctorInfoOutDTO doctorInfo = tDoctorInfoService.getInfo(subscribeInfoDO.getBusinessId());
        transform.setHospitalName(doctorInfo.getHospitalName());
        transform.setDoctorName(doctorInfo.getDoctorName());
        return transform;
    }

    @Override
    public InstitutionInfoResponse showInstitutionDetail(Integer id) {
        //根据id查询预约表信息
        SubscribeInfoDO subscribeInfoDO = this.getById(id);
        if(subscribeInfoDO == null){
            throw new TransitException("预约信息不存在");
        }
        InstitutionInfoResponse transform = InstitutionInfoResponse.transform(subscribeInfoDO);
        if(transform.getMedicalInsuranceType()!= null){
            Map<String, String> medicalInsurance = showDictType2Map("medical_insurance");
            transform.setMedicalInsuranceTypeStr(medicalInsurance.get(transform.getMedicalInsuranceType()));
            /*List<DictResponse> medicalInsurance = showDictType("medical_insurance");
            for (DictResponse dictResponse : medicalInsurance) {
                if(dictResponse.getId().equals(transform.getMedicalInsuranceType())){
                    transform.setMedicalInsuranceTypeStr(dictResponse.getName());
                    break;
                }
            }*/
        }
        if(transform.getRelationType()!= null){
            Map<String, String> relationType = showDictType2Map("relation");
            transform.setRelationTypeStr(relationType.get(transform.getRelationType()));
        }

        //根据业务id查询机构表得到机构名称，机构详细地址，机构类型
        TOrganInfoDTO info = tOrganInfoService.getInfo(subscribeInfoDO.getBusinessId());
        if(info== null){
            throw new TransitException("机构信息不存在");
        }
        transform.setOrganName(info.getOrganName());
        transform.setRegionDetailInfo(info.getRegionDetailInfo());
        transform.setRegionCode(info.getRegionCode());
        SystemCity cityByAreaCode = systemCityService.getCityByAreaCode(info.getRegionCode());
        transform.setRegionCodeStr(cityByAreaCode.getName());
        transform.setOrganType(info.getOrganType());
        return transform;
    }

    @Override
    @Transactional
    public String diagnosisModify(ApptModifyInfoRequest request,Integer userId) {
        boolean valid = PhoneValidator.isValid(request.getUserOrderPhone());
        if (!valid) {
            throw  new TransitException("手机号格式错误");
        }
        //获取用户id

        SubscribeInfoDO transform = ApptAddInfoRequest.transform(request);
        transform.setId(request.getId());
        transform.setUpdateUserId(userId);
        boolean update = this.updateById(transform);
        if(!update){
            throw new TransitException("修改失败");
        }
        return transform.getId().toString();
    }

    @Override
    public String institutionModify(InstModifyInfoRequest request, Integer userId ) {
        boolean valid = PhoneValidator.isValid(request.getUserOrderPhone());
        if (!valid) {
            throw  new TransitException("手机号格式错误");
        }

        SubscribeInfoDO transform = InstModifyInfoRequest.transform(request);
        transform.setId(request.getId());
        transform.setUpdateUserId(userId);
        boolean update = this.updateById(transform);
        if(!update){
            throw new TransitException("修改失败");
        }
        return transform.getId().toString();
    }

    @Override
    public BasePage<DiagnosisInfoResponse> listApptPage(ApptInfoQuery query, PageParamRequest pageRequest) {
        PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
        LambdaQueryWrapper<SubscribeInfoDO> queryWrapper = new LambdaQueryWrapper<>();
        if(query.getBusinessType() != null){
            queryWrapper.eq(SubscribeInfoDO::getBusinessType, query.getBusinessType());
        }else{
            //查类型不为2的
            queryWrapper.ne(SubscribeInfoDO::getBusinessType, BusinessTypeEnum.INSTITUTION_APPT.getCode());
        }
        if(query.getStatus() != null){
            queryWrapper.eq(SubscribeInfoDO::getStatus, query.getStatus());
        }
        if(query.getBeginTime()!= null && !query.getBeginTime().isEmpty()){
            queryWrapper.between(SubscribeInfoDO::getCreateTime, query.getBeginTime(), query.getEndTime());
        }
        if(query.getAsc() != null){
            queryWrapper.orderByAsc(SubscribeInfoDO::getCreateTime);
        }else{
            queryWrapper.orderByDesc(SubscribeInfoDO::getCreateTime);
        }
        if(query.getKeywords() != null && !query.getKeywords().isEmpty()){
            queryWrapper.like(SubscribeInfoDO::getUserOrderName, query.getKeywords())
                    .or().like(SubscribeInfoDO::getLivingAbility, query.getKeywords())
                    .or().like(SubscribeInfoDO::getDiseaseName, query.getKeywords());
        }
        //获取登录用户id 如果不为null则证明是用户查看我的预约，否则是管理端
        Integer userId = userService.getUserId();
        if(userId != null && userId != 0){
            queryWrapper.eq(SubscribeInfoDO::getAppUserId, userId);
        }
        List<SubscribeInfoDO> subscribeInfoDOList = baseMapper.selectList(queryWrapper);
        if(CollUtil.isEmpty(subscribeInfoDOList)){
            return BasePage.restPage(new ArrayList<>());
        }
        BasePage<SubscribeInfoDO> basePage = BasePage.restPage(subscribeInfoDOList);
        ArrayList<DiagnosisInfoResponse> arrayList = new ArrayList<>(subscribeInfoDOList.size());
        for (SubscribeInfoDO infoDO : subscribeInfoDOList) {
            DiagnosisInfoResponse transform = DiagnosisInfoResponse.transform(infoDO);
            TDoctorInfoDO tDoctorInfoDO = tDoctorInfoService.getById(infoDO.getBusinessId());

            transform.setHospitalName(tDoctorInfoDO.getBelongingHospital());
            transform.setDoctorName(tDoctorInfoDO.getDoctorName());
            arrayList.add(transform);
        }
        BasePage<DiagnosisInfoResponse> diagnosisInfoResponseBasePage = BasePage.restPage(arrayList);
        BeanUtils.copyProperties(basePage, diagnosisInfoResponseBasePage,"list");
        return diagnosisInfoResponseBasePage;
    }

    @Override
    public BasePage<InstPageInfoResponse> listInstPage(InstInfoQuery query, PageParamRequest pageRequest) {
        PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
        LambdaQueryWrapper<SubscribeInfoDO> queryWrapper = new LambdaQueryWrapper<>();

        if(query.getStatus() != null){
            queryWrapper.eq(SubscribeInfoDO::getStatus, query.getStatus());
        }
        if(query.getBeginTime()!= null && !query.getBeginTime().isEmpty()){
            queryWrapper.between(SubscribeInfoDO::getCreateTime, query.getBeginTime(), query.getEndTime());
        }
        if(query.getAsc() != null){
            queryWrapper.orderByAsc(SubscribeInfoDO::getCreateTime);
        }else{
            queryWrapper.orderByDesc(SubscribeInfoDO::getCreateTime);
        }
        if(query.getKeywords() != null && !query.getKeywords().isEmpty()){
            queryWrapper.like(SubscribeInfoDO::getUserOrderName, query.getKeywords())
                    .or().like(SubscribeInfoDO::getTransferAddress, query.getKeywords())
                    .or().like(SubscribeInfoDO::getHealthStatus, query.getKeywords());
        }
        //获取登录用户id 如果不为null则证明是用户查看我的预约，否则是管理端
        Integer userId = userService.getUserId();

        if(userId != null && userId != 0){
            queryWrapper.eq(SubscribeInfoDO::getAppUserId, userId);
        }
        //查类型为2的
        queryWrapper.eq(SubscribeInfoDO::getBusinessType, BusinessTypeEnum.INSTITUTION_APPT.getCode());
        List<SubscribeInfoDO> subscribeInfoDOList = this.list(queryWrapper);
        if(CollUtil.isEmpty(subscribeInfoDOList)){
            return BasePage.restPage(new ArrayList<>());
        }
        BasePage<SubscribeInfoDO> basePage = BasePage.restPage(subscribeInfoDOList);
        ArrayList<InstPageInfoResponse> arrayList = new ArrayList<>(subscribeInfoDOList.size());
        for (SubscribeInfoDO infoDO : subscribeInfoDOList) {
            InstPageInfoResponse transform = InstPageInfoResponse.transform(infoDO);
            //TOrganInfoDO tOrganInfoDO = tOrganInfoDOS.get(infoDO.getBusinessId());
            TOrganInfoDO tOrganInfoDO = tOrganInfoService.getById(infoDO.getBusinessId());
            transform.setOrganName(tOrganInfoDO.getOrganName());
            transform.setOrganType(tOrganInfoDO.getOrganType());
            arrayList.add(transform);
        }
        BasePage<InstPageInfoResponse> instPageInfoResponseBasePage = BasePage.restPage(arrayList);
        BeanUtils.copyProperties(basePage, instPageInfoResponseBasePage,"list");
        return instPageInfoResponseBasePage;
    }

    @Override
    @Transactional
    public void appointmentCancel(Integer id, Integer code,Integer userId) {
        SubscribeInfoDO subscribeInfoDO = this.getById(id);
        if(subscribeInfoDO == null){
            throw new TransitException("预约不存在！");
        }
        if(subscribeInfoDO.getStatus().equals(AppointmentStatusEnum.CANCELED.getCode())){
            throw new TransitException("该预约已取消！");
        }
        if(userId != null && !userId.equals(subscribeInfoDO.getAppUserId()) && userId != 0){
            throw new TransitException("您没有权限取消该预约！");
        }
        subscribeInfoDO.setStatus(code);
        if(userId != null && userId != 0){
            subscribeInfoDO.setUpdateUserId(userId);
            this.updateById(subscribeInfoDO);
        }else{
            this.updateById(subscribeInfoDO);
        }
    }
    /**
     * 修改预约状态
     * @param id 预约id
     * @param status 预约状态
     * @return
     */
    @Override
    public void modifyStatus(Integer id, Integer status) {
        SubscribeInfoDO infoDO = getById(id);
        if(infoDO == null){
            throw new TransitException("预约不存在");
        }
        if(Objects.equals(infoDO.getStatus(), status)){
            throw new TransitException("预约已处理");
        }
        infoDO.setStatus(status);
        boolean update = updateById(infoDO);
        if(!update){
            throw new TransitException("修改状态失败");
        }
    }


    public List<DictResponse> showDictType(String dictName) {
        List<SystemConfig> insuranceType = systemConfigService.lambdaQuery()
                .eq(SystemConfig::getName, dictName)
                .eq(SystemConfig::getStatus, 0).list();
        List<DictResponse> responses =new ArrayList<>(insuranceType.size());
        if(CollUtil.isNotEmpty(insuranceType)){
            for (SystemConfig systemConfig : insuranceType) {
                DictResponse dictResponse = new DictResponse();
                dictResponse.setKey(systemConfig.getTitle());
                dictResponse.setValue(systemConfig.getValue());
                responses.add(dictResponse);
            }
        }
        return responses;
    }



    public Map<String, String> showDictType2Map(String dictName){
        List<SystemConfig> insuranceType = systemConfigService.lambdaQuery()
                .eq(SystemConfig::getName, dictName)
                .eq(SystemConfig::getStatus, 0).list();
        if(CollUtil.isEmpty(insuranceType)){
            return new HashMap<>();
        }
        return insuranceType.stream().collect(Collectors.toMap(SystemConfig::getValue, SystemConfig::getTitle));
    }
}
